package com.kfm.jdbc.day0327;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 操作数据库的工具类
 */
public class DBUtils<T> {

    private String url;

    private String user;

    private String password;

    private Connection conn;

    private PreparedStatement statement;

    private ResultSet resultSet;

    static {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public DBUtils(String url, String user, String password){
        this.url = url;
        this.user = user;
        this.password = password;
    }

    private Connection getConnection(){
        if (url != null && user != null && password != null){
            try {
                if (conn == null){
                    conn = DriverManager.getConnection(url, user, password);
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
            return conn;
        }
        throw new NullPointerException("数据库连接参数未设置");
    }

    public T selectOne(String sql, Recover<T> recover, Object...params){
        // try-with-resources
//        try {
//            executeSQL(sql, params);
//
//            resultSet = statement.executeQuery();
//
//            if (resultSet.next()){
//                return recover.recover(resultSet);
//            }
//        } catch (SQLException e) {
//            throw new RuntimeException(e);
//        }
//        return null;

        List<T> select = select(sql, recover, params);

        return select.size() > 0? select.get(0) : null;
    }

    public T selectOne(String sql, Class<T> cla, Object...params){
        T t = null;
        try {
            t = cla.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }


        return t;
    }

    public List<T> select(String sql, Recover<T> recover, Object...params){
        resultSet = select(sql, params);
        List<T> list = new ArrayList<>();
        try {
            while (resultSet.next()){
                list.add(recover.recover(resultSet));
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return list;
    }

    public ResultSet select(String sql, Object...params){

        // try-with-resources
        try {
            executeSQL(sql, params);

            return statement.executeQuery();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public int update(String sql, Object...params){
        // try-with-resources
        try {
            executeSQL(sql, params);
            return statement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    private void executeSQL(String sql, Object...params){
        try {
            conn = getConnection();
            statement = conn.prepareStatement(sql);

            // 设置值
            for (int i = 0; i < params.length; i++) {
                statement.setObject(i + 1, params[i]);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public void close(){
        try {
            if (resultSet != null) {
                resultSet.close();
            }

            if (statement != null) {
                statement.close();
            }

            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }


}
